﻿/*
Copyright 2009 Matías Fidemraizer (www.matiasfidemraizer.com).

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

using System;
using System.Collections;
using System.Collections.Generic;

namespace Comkarl.Architecture.Patterns.DomainModel
{
    /// <summary>
    /// Represents the base class for a repository (implementation of "Repository pattern").
    /// </summary>
    /// <typeparam name="TIdentifierName">
    /// The type for the stored domain object identifier's name.
    /// </typeparam>
    /// <typeparam name="TDomainObject">
    /// The type for the stored domain object.
    /// </typeparam>
    public abstract class Repository<TDomainObjectIdentiferName, TDomainObject> 
        : PatternInstanceMember<TDomainObjectIdentiferName, PatternInstance<TDomainObjectIdentiferName>>
        where TDomainObjectIdentiferName : IEquatable<TDomainObjectIdentiferName>
        where TDomainObject : DomainObject<TDomainObjectIdentiferName>
    {
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="id">
        /// The unique identifier for the repository.
        /// </param>
        public Repository(RepositoryIdentifier<TDomainObjectIdentiferName> id)
            : base(id)
        {
        }

        /// <summary>
        /// Exposes an indexed access to stored domain objects.
        /// </summary>
        /// <param name="id">
        /// The unique identifier for the desired domain object.
        /// </param>
        /// <returns>
        /// The desired domain object.
        /// </returns>
        public virtual TDomainObject this[DomainObjectIdentifier<TDomainObjectIdentiferName> id]
        {
            get
            {
                return GetByID(id);
            }
        }

        /// <summary>
        /// Gets an stored domain object by its unique identifier.
        /// </summary>
        /// <param name="id">
        /// The unique identifier for the stored domain object.
        /// </param>
        /// <returns>
        /// The desired domain object.
        /// </returns>
        public abstract TDomainObject GetByID(DomainObjectIdentifier<TDomainObjectIdentiferName> id);

        /// <summary>
        /// Adds a domain object to the store.
        /// </summary>
        /// <param name="newObject">
        /// The domain object to be stored.
        /// </param>
        public abstract void Add(TDomainObject newObject);

        /// <summary>
        /// Updates a stored domain object in the store with a new state.
        /// </summary>
        /// <param name="someObject">
        /// The stored domain object to update its state.
        /// </param>
        public abstract void Update(TDomainObject someObject);

        /// <summary>
        /// Removes a stored domain object.
        /// </summary>
        /// <param name="someObject">
        /// The domain object to remove.
        /// </param>
        public abstract void Remove(TDomainObject someObject);
    }
}